﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ComponentModel;

namespace Relay.Core.Plugins {
    /// <summary>
    /// Loads plugins from a file.
    /// </summary>
    public class PluginLoader {
        #region Fields
        private readonly string _fileName = String.Empty;

        private readonly Assembly _assembly = null;
        #endregion

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the <see cref="PluginLoader"/> class.
        /// </summary>
        /// <param name="filename">The filename of the plugin DLL.</param>
        public PluginLoader(string filename) {
            _fileName = filename;
            _assembly = Assembly.LoadFile(filename);
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Gets the plugins in this assembly.
        /// </summary>
        /// <returns>An array of types representing the plugins in the assembly.</returns>
        public Type[] GetPlugins() {
            return
                (from type in _assembly.GetTypes()
                where type.GetInterfaces().Contains(typeof(IPlugin))
                select type).ToArray();
        }

        /// <summary>
        /// Gets a plugin <see cref="Type"/> given its name.
        /// </summary>
        /// <param name="name">The name of the plugin.</param>
        /// <returns>A plugin type.</returns>
        public Type GetPluginByName(string name) {
            Type type = _assembly.GetType(name);
            if (type == null || !type.GetInterfaces().Contains(typeof(IPlugin)))
                return null;
            else
                return type;
        }

        /// <summary>
        /// Creates an instance of a plugin.
        /// </summary>
        /// <param name="className">Name of the plugin class.</param>
        /// <returns>An instance of the specified plugin</returns>
        public IPlugin CreateInstance(Type plugin) {
            return TypeDescriptor.CreateInstance(null, plugin, null, null) as IPlugin;
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets the filename of the assembly.
        /// </summary>
        /// <value>The filename.</value>
        public string Filename {
            get { return _fileName; }
        } 
        #endregion
    }
}
